package com.farm.code.server;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.farm.core.auth.domain.LoginUser;
import com.farm.core.time.TimeTool;

import org.apache.commons.beanutils.BeanUtils;

import com.farm.code.dao.FarmCodeFieldDaoInter;
import com.farm.code.dao.FarmCodeGuideDaoInter;
import com.farm.code.dao.FarmCodePackageDaoInter;
import com.farm.code.dao.FarmCodeTempletDaoInter;
import com.farm.code.domain.FarmCodeField;
import com.farm.code.domain.FarmCodeGuide;
import com.farm.code.domain.FarmCodePackage;
import com.farm.code.domain.FarmCodeProject;
import com.farm.code.domain.FarmCodeTemplet;
import com.farm.code.jdbc.DataSourceConf;
import com.farm.code.jdbc.JdbcUtil;
import com.farm.code.server.FarmCodeGuideManagerInter;
import com.farm.core.sql.query.DBRule;
import com.farm.core.sql.query.DataQuery;
import com.farm.core.sql.result.DataResult;

import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * 代码工程运行向导
 * 
 * @author MAC_wd
 */
public class FarmCodeGuideManagerImpl implements FarmCodeGuideManagerInter {
	private FarmCodeGuideDaoInter farmCodeGuideDao;
	private FarmCodeProjectManagerInter projectServer;
	private FarmCodeFieldDaoInter farmCodeFieldDao;
	private FarmCodePackageDaoInter farmCodePackageDao;
	private FarmCodeTempletDaoInter farmCodeTempletDao;
//	private static final Logger log = Logger
//			.getLogger(FarmCodeGuideManagerImpl.class);

	@Override
	public FarmCodeGuide insertFarmCodeGuideEntity(FarmCodeGuide entity,
			com.farm.core.auth.domain.LoginUser user) {
		entity.setCuser(user.getId());
		entity.setCtime(TimeTool.getTimeDate14());
		entity.setCusername(user.getName());
		entity.setEuser(user.getId());
		entity.setEusername(user.getName());
		entity.setEtime(TimeTool.getTimeDate14());
		entity.setPstate("1");
		return farmCodeGuideDao.insertEntity(entity);
	}

	@Override
	public FarmCodeGuide editFarmCodeGuideEntity(FarmCodeGuide entity,
			LoginUser user) {
		// TODO 自动生成代码,修改后请去除本注释
		FarmCodeGuide entity2 = farmCodeGuideDao.getEntity(entity.getId());
		// entity2.setEuser(user.getId());
		// entity2.setEusername(user.getName());
		// entity2.setEtime(TimeTool.getTimeDate14());
		entity2.setDbdriverclass(entity.getDbdriverclass());
		entity2.setDburl(entity.getDburl());
		entity2.setDbusername(entity.getDbusername());
		entity2.setDbpassword(entity.getDbpassword());
		entity2.setTablename(entity.getTablename());
		entity2.setAppcode(entity.getAppcode());
		entity2.setApprandom(entity.getApprandom());
		entity2.setAppname(entity.getAppname());
		entity2.setComcode(entity.getComcode());
		entity2.setProcode(entity.getProcode());
		entity2.setComtype(entity.getComtype());
		farmCodeGuideDao.editEntity(entity2);
		return entity2;
	}

	@Override
	public void deleteFarmCodeGuideEntity(String entity, LoginUser user) {
		// TODO 自动生成代码,修改后请去除本注释
		farmCodeGuideDao.deleteEntity(farmCodeGuideDao.getEntity(entity));
	}

	@Override
	public FarmCodeGuide getFarmCodeGuideEntity(String id) {
		// TODO 自动生成代码,修改后请去除本注释
		if (id == null) {
			return null;
		}
		return farmCodeGuideDao.getEntity(id);
	}

	@Override
	public DataQuery createFarmCodeGuideSimpleQuery(DataQuery query) {
		// TODO 自动生成代码,修改后请去除本注释
		DataQuery dbQuery = DataQuery
				.init(
						query,
						"farm_code_guide",
						"id,DBDRIVERCLASS,DBURL,DBUSERNAME,DBPASSWORD,TABLENAME,APPCODE,APPRANDOM,APPNAME,COMCODE,PROCODE,COMTYPE");
		return dbQuery;
	}

	// ----------------------------------------------------------------------------------

	@Override
	public FarmCodeGuide editProjectJDBCSetings(String projectid,
			FarmCodeGuide entity, LoginUser currentUser) {
		FarmCodeProject project = projectServer
				.getFarmCodeProjectEntity(projectid);
		FarmCodeGuide guide = null;
		if (project.getGuideid() != null) {
			guide = getFarmCodeGuideEntity(project.getGuideid());
		}
		if (guide == null) {
			entity.setAppcode("TableName");
			entity.setAppname("应用功能");
			entity.setComcode("farm");
			entity.setComtype("com");
			entity.setProcode("core");
			entity.setApprandom("0");
			guide = insertFarmCodeGuideEntity(entity, currentUser);
			project.setGuideid(guide.getId());
			projectServer.editFarmCodeProjectEntity(project, currentUser);
		} else {
			guide.setDbdriverclass(entity.getDbdriverclass());
			guide.setDbpassword(entity.getDbpassword());
			guide.setDburl(entity.getDburl());
			guide.setDbusername(entity.getDbusername());
			editFarmCodeGuideEntity(guide, currentUser);
		}
		return guide;
	}

	@Override
	public List<String> getDatabaseTables(FarmCodeGuide jdbcsetings) {
		try {
			return JdbcUtil.getTables(new DataSourceConf(jdbcsetings
					.getDbdriverclass(), jdbcsetings.getDburl(), jdbcsetings
					.getDbusername(), jdbcsetings.getDbpassword()));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public DataResult getDatabaseField(FarmCodeGuide jdbcAndTableSetings) {
		try {
			List<Map<String, Object>> list = JdbcUtil.getFieldType(
					new DataSourceConf(jdbcAndTableSetings.getDbdriverclass(),
							jdbcAndTableSetings.getDburl(), jdbcAndTableSetings
									.getDbusername(), jdbcAndTableSetings
									.getDbpassword()), jdbcAndTableSetings
							.getTablename());
			return DataResult.getInstance(list, list.size(), 1, list.size());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public FarmCodeGuideDaoInter getFarmCodeGuideDao() {
		return farmCodeGuideDao;
	}

	public void setFarmCodeGuideDao(FarmCodeGuideDaoInter farmCodeGuideDao) {
		this.farmCodeGuideDao = farmCodeGuideDao;
	}

	public FarmCodeProjectManagerInter getProjectServer() {
		return projectServer;
	}

	public void setProjectServer(FarmCodeProjectManagerInter projectServer) {
		this.projectServer = projectServer;
	}

	public FarmCodeFieldDaoInter getFarmCodeFieldDao() {
		return farmCodeFieldDao;
	}

	public void setFarmCodeFieldDao(FarmCodeFieldDaoInter farmCodeFieldDao) {
		this.farmCodeFieldDao = farmCodeFieldDao;
	}

	@Override
	public FarmCodeGuide editProjectAppSetings(String projectid,
			FarmCodeGuide entity, LoginUser currentUser) {
		FarmCodeProject project = projectServer
				.getFarmCodeProjectEntity(projectid);
		FarmCodeGuide guide = getFarmCodeGuideEntity(project.getGuideid());
		if (guide == null) {
			guide = new FarmCodeGuide();
			guide.setTablename(entity.getTablename());
			guide.setAppcode(entity.getAppcode());
			guide.setApprandom(entity.getApprandom());
			guide.setAppname(entity.getAppname());
			guide.setComtype(entity.getComtype());
			guide.setComcode(entity.getComcode());
			guide.setProcode(entity.getProcode());
			guide = insertFarmCodeGuideEntity(entity, currentUser);
			project.setGuideid(guide.getId());
			projectServer.editFarmCodeProjectEntity(project, currentUser);
		} else {
			guide.setTablename(entity.getTablename());
			guide.setAppcode(entity.getAppcode());
			guide.setApprandom(entity.getApprandom());
			guide.setAppname(entity.getAppname());
			guide.setComtype(entity.getComtype());
			guide.setComcode(entity.getComcode());
			guide.setProcode(entity.getProcode());
			editFarmCodeGuideEntity(guide, currentUser);
		}

		return guide;
	}

	@Override
	public void editFarmCodeGuideTableField(String projectid,
			List<Map<String, Object>> fields) {
		FarmCodeProject project = projectServer
				.getFarmCodeProjectEntity(projectid);
		FarmCodeGuide guide = getFarmCodeGuideEntity(project.getGuideid());
		// 先删除guide下的所有字段再将字段添加到数据库中
		List<DBRule> list = new ArrayList<DBRule>();
		list.add(new DBRule("GUIDEID", guide.getId(), "="));
		farmCodeFieldDao.deleteEntitys(list);
		// 将新字段加入列表中
		for (Map<String, Object> field : fields) {
			FarmCodeField fieldObj = new FarmCodeField();
			Object formtype = field.get("FFORMTYPE");
			fieldObj.setFformtype(formtype.toString());
			Object name = field.get("NAME");
			fieldObj.setFcode(name.toString());
			Object nullAble = field.get("NULLABLE");
			if (nullAble != null && nullAble.equals("1")) {
				fieldObj.setFmandatory("0");
			} else {
				fieldObj.setFmandatory("1");
			}
			Object limitType = field.get("FLIMITTYPE");
			if (limitType == null || limitType.toString() == null
					|| limitType.toString().trim().length() <= 0) {
				fieldObj.setFlimittype("NONE");
			} else {
				fieldObj.setFlimittype(limitType.toString());
			}

			Object pkIs = field.get("FPK");
			if (pkIs == null || pkIs.toString() == null
					|| pkIs.toString().trim().length() <= 0) {
				fieldObj.setFpk("0");
			} else {
				fieldObj.setFpk("1");
			}
			Object size = field.get("SIZE");
			if (size == null || size.toString() == null
					|| size.toString().trim().length() <= 0) {
				fieldObj.setFlength(0);
			} else {
				fieldObj.setFlength(Integer.valueOf(size.toString()));
			}
			Object type = field.get("TYPE");
			fieldObj.setFdatatype(type.toString());
			Object title = field.get("TITLE");
			fieldObj.setFname(title.toString());
			// -----------------
			fieldObj.setGuideid(guide.getId());
			fieldObj.setCtime(TimeTool.getTimeDate14());
			fieldObj.setCuser("NONE");
			fieldObj.setCusername("NONE");
			fieldObj.setEtime(TimeTool.getTimeDate14());
			fieldObj.setEuser("NONE");
			fieldObj.setEusername("NONE");
			fieldObj.setPstate("1");
			farmCodeFieldDao.insertEntity(fieldObj);
		}
	}

	@Override
	public Map<String, Object> getTemplateParas(String projectid) {
		try {
			Map<String, Object> map = new HashMap<String, Object>();
			FarmCodeProject project = projectServer
					.getFarmCodeProjectEntity(projectid);
			FarmCodeGuide guide = (FarmCodeGuide) BeanUtils
					.cloneBean(getFarmCodeGuideEntity(project.getGuideid()));
			// 随机数
			if (guide.getApprandom().equals("1")) {
				guide.setAppcode(guide.getAppcode()
						+ String.valueOf(new Date().getTime()).substring(8));
			}
			List<DBRule> list = new ArrayList<DBRule>();
			list.add(new DBRule("GUIDEID", guide.getId(), "="));
			List<FarmCodeField> fields = farmCodeFieldDao.selectEntitys(list);
			{
				// 构造变量---********************------------------
				map.put("project", project);
				map.put("guide", guide);
				map.put("fields", fields);
			}
			// 包
			List<DBRule> listPackageRule = new ArrayList<DBRule>();
			listPackageRule.add(new DBRule("PROID", projectid, "="));
			List<FarmCodePackage> packs = farmCodePackageDao
					.selectEntitys(listPackageRule);
			List<Map<String, Object>> packList = new ArrayList<Map<String, Object>>();
			map.put("packs", packList);
			for (FarmCodePackage pack : packs) {
				Map<String, Object> packMap = new HashMap<String, Object>();
				{
					// 构造变量---********************------------------
					packMap.put("packcode", parseCodeMark(guide, pack
							.getPackcode()));
					packMap.put("packname", parseCodeMark(guide, pack
							.getPackname()));
					packMap.put("packpath", parseCodeMark(guide, pack
							.getPackcode().replace(".", File.separator)
							.replace("/", File.separator).replace("\\",
									File.separator)));
					packMap.put("packcodetitle", pack.getPackcode().replace(
							".", "_")
							+ "_code");
					packMap.put("packpathtitle", pack.getPackcode().replace(
							".", "_")
							+ "_path");
					map.put(pack.getPackcode().replace(".", "_") + "_code",
							packMap.get("packcode"));
					map.put(pack.getPackcode().replace(".", "_") + "_path",
							packMap.get("packpath"));

				}
				// 文件
				{
					List<FarmCodeTemplet> tempList = new ArrayList<FarmCodeTemplet>();
					packMap.put("files", tempList);
					List<DBRule> listTemplateRule = new ArrayList<DBRule>();
					listTemplateRule
							.add(new DBRule("PACKID", pack.getId(), "="));
					List<FarmCodeTemplet> templates = farmCodeTempletDao
							.selectEntitys(listTemplateRule);
					for (FarmCodeTemplet template : templates) {
						FarmCodeTemplet tem = (FarmCodeTemplet) BeanUtils
								.cloneBean(template);
						{
							// 构造变量---********************------------------
							tem.setTemcontent(null);
							tem.setFilename(parseCodeMark(guide, tem
									.getFilename()));
							tem.setPcontent(template.getFilename().replace(".",
									"_"));
							map.put(template.getFilename().replace(".", "_"),
									tem.getFilename());
						}
						tempList.add(tem);
					}
				}
				packList.add(packMap);
			}
			return map;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 将包和文件名中的转义字符转码
	 * 
	 * @param guide
	 * @param code
	 * @return
	 */
	private String parseCodeMark(FarmCodeGuide guide, String code) {
		// 构建参数 F8501:机构类型小写, F8502:机构代码小写, F8503:项目代码小写, F8504:功能代码小写,
		// F8505:功能代码大写, F8506:功能代码首字母大写
		String p8501 = guide.getComtype().toLowerCase();
		String p8502 = guide.getComcode().toLowerCase();
		String p8503 = guide.getProcode().toLowerCase();
		String p8504 = guide.getAppcode().toLowerCase();
		String p8505 = guide.getAppcode().toUpperCase();
		String p8506 = null;
		String appcode = guide.getAppcode();
		if (appcode.length() > 1) {
			p8506 = appcode.substring(0, 1).toUpperCase()
					+ appcode.substring(1).toLowerCase();
		} else {
			p8506 = p8505;
		}
		code = code.replaceAll("F8501", p8501);
		code = code.replaceAll("F8502", p8502);
		code = code.replaceAll("F8503", p8503);
		code = code.replaceAll("F8504", p8504);
		code = code.replaceAll("F8505", p8505);
		code = code.replaceAll("F8506", p8506);
		return code;
	}

	public FarmCodePackageDaoInter getFarmCodePackageDao() {
		return farmCodePackageDao;
	}

	public void setFarmCodePackageDao(FarmCodePackageDaoInter farmCodePackageDao) {
		this.farmCodePackageDao = farmCodePackageDao;
	}

	public FarmCodeTempletDaoInter getFarmCodeTempletDao() {
		return farmCodeTempletDao;
	}

	public void setFarmCodeTempletDao(FarmCodeTempletDaoInter farmCodeTempletDao) {
		this.farmCodeTempletDao = farmCodeTempletDao;
	}

	private static Configuration templateCfg = new Configuration();

	@Override
	public void runTemplate(String projectid, String workpath) {
		try {
			FarmCodeProject project = projectServer
					.getFarmCodeProjectEntity(projectid);
			FarmCodeGuide guide = (FarmCodeGuide) BeanUtils
					.cloneBean(getFarmCodeGuideEntity(project.getGuideid()));
			StringTemplateLoader stringLoader = new StringTemplateLoader();
			Map<String, Object> map = getTemplateParas(projectid);
			// 随机数
			if (guide.getApprandom().equals("1")) {
				guide.setAppcode(guide.getAppcode()
						+ String.valueOf(new Date().getTime()).substring(8));
			}
			// 包
			List<DBRule> listPackageRule = new ArrayList<DBRule>();
			listPackageRule.add(new DBRule("PROID", projectid, "="));
			List<FarmCodePackage> packs = farmCodePackageDao
					.selectEntitys(listPackageRule);
			for (FarmCodePackage pack : packs) {
				// 文件
				{
					List<DBRule> listTemplateRule = new ArrayList<DBRule>();
					listTemplateRule
							.add(new DBRule("PACKID", pack.getId(), "="));
					List<FarmCodeTemplet> templates = farmCodeTempletDao
							.selectEntitys(listTemplateRule);
					for (FarmCodeTemplet codetemplate : templates) {
						FileOutputStream fops = null;
						Writer out = null;

						stringLoader.putTemplate(codetemplate.getId(),
								codetemplate.getTemcontent());
						templateCfg.setTemplateLoader(stringLoader);
						Template template;
						template = templateCfg.getTemplate(
								codetemplate.getId(), "utf-8");
						String path = (workpath
								+ File.separator
								+ parseCodeMark(guide, pack.getPackcode())
										.replace(".", "/") + File.separator + parseCodeMark(
								guide, codetemplate.getFilename())).replace(
								"/", "\\").replace("\\", File.separator);
						File outPutFile = new File(path);
						outPutFile.getParentFile().mkdirs();
						try {
							fops = new FileOutputStream(outPutFile);
							out = new OutputStreamWriter(fops, "utf-8");
							template.process(map, out);
						} finally {
							fops.close();
							out.close();
						}
					}
				}
			}
			project.setDirpath(workpath);
			LoginUser user = new LoginUser() {
				@Override
				public String getName() {
					return "none";
				}

				@Override
				public String getLoginname() {
					return "none";
				}

				@Override
				public String getId() {
					return "none";
				}
			};
			projectServer.editFarmCodeProjectEntity(project, user);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}
